(in-package :iorek)

(defgeneric print-object (object stream))

(defmethod print-object (object stream)
  ;;Fall back to the CL printer
  (write object :stream stream))

(defmethod print-object ((symbol symbol) stream)
  ;;TODO print full form via some switch
  (when (and
         (not (eq (find-symbol (symbol-name symbol) *namespace* nil)
                  symbol))
         (symbol-namespace symbol)
         (not (eq (symbol-namespace symbol) *namespace*)))
    (print-object (symbol-namespace symbol) stream)
    (princ ":" stream))
  (princ (symbol-name symbol) stream))

(defmethod print-object ((object fset:wb-seq) stream)
  (princ #\( stream)
  (let (space)
    (fset:do-seq (el object)
      (if space (princ " " stream) (setf space t))
      (print-object el stream)))
  (princ #\) stream)
  object)

(defmethod print-object ((object cl:vector) stream)
  (princ #\[ stream)
  (let (space)
    (loop
       :for el :across object
       :do (if space (princ " " stream) (setf space t))
       :do (print-object el stream)))
  (princ #\] stream)
  object)

(defmethod print-object ((object fset:wb-map) stream)
  (princ #\{ stream)
  (let (space)
    (fset:do-map (k v object)
      (if space (princ " " stream) (setf space t))
      (print-object k stream)
      (princ " " stream)
      (print-object v stream)))
  (princ #\} stream)
  object)

(defmethod print-object ((object complex) stream)
  (if (zerop (realpart object))
      (progn
        (print-object (imagpart object) stream)
        (princ "i" stream))
      (progn
        (princ #\[ stream)
        (print-object (realpart object) stream)
        (princ " + " stream)
        (print-object (imagpart object) stream)
        (princ "i" stream)
        (princ #\] stream)))
  object)